#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import stat
from dataclasses import dataclass
from enum import Enum
from pydantic import BaseModel, Field
from common.env_common import get_install_head_path


class CertParam:
    PRO_CERT_PEM = "job_protectEnv_extendInfo_caCertPem_"
    PRO_CERT_KEY = "job_protectEnv_extendInfo_clientKey_"
    PRO_CERT_RP = "job_protectEnv_auth_extendInfo_randPass_"
    TAR_CERT_PEM = "job_targetObject_extendInfo_caCertPem_"
    TAR_CERT_KEY = "job_targetObject_extendInfo_clientKey_"
    TAR_CERT_RP = "job_targetObject_auth_extendInfo_randPass_"


class RoachConstant:
    XBSA_FILE = f"{get_install_head_path()}/DataBackup/ProtectClient/ProtectClient-E/stmp"
    BUSINESS_CONFIG_FILE = "business_config.txt"
    # 端口号位置
    ADDRESS_FAMILY_AF_INET = 2
    ROACH_DATA_FILE_PATH = 2
    # backUpAgent进程信息
    PROCESS_NAME = "backUpAgent"
    PROCESS_MAIN_NAME = "back"
    PROCESS_SUB_NAME = "host"
    # 挂载目录
    TPOPS_FILESYSTEM_MOUNT_PATH = "/mnt/databackup"
    # xbsa资源信息目录
    AGENT_STMP_PATH = f"{get_install_head_path()}/DataBackup/ProtectClient/ProtectClient-E/stmp"
    # 资源路径白名单
    WHITE_FILE_LIST = [TPOPS_FILESYSTEM_MOUNT_PATH, AGENT_STMP_PATH]
    # xbsa.conf文件默认路径
    XBSA_FILE_DEFAULT_PATH = "/home/backupagent/xbsa.conf"
    # 下发备份任务时所置值，用于区分任务类型
    XBSA_FILE_BACKUP_PATH = "/home/myuser/xbsa_backup.conf"
    # 下发恢复任务时所置值，用于区分任务类型
    XBSA_FILE_RESTORE_PATH = "/home/myuser/xbsa_restore.conf"
    # xbsa ip位置
    BACKUP_AGENT_IP_POS = 2
    # xbsa port位置
    BACKUP_AGENT_PORT_POS = 3


class BackupCmd:
    BACKUP_PRE = "backup_pre"


class ErrorCode(int, Enum):
    ERROR_INCREMENT_TO_FULL = 1577209901
    ERROR_DIFFERENT_VERSION = 1577209971
    ERROR_DIFFERENT_TOPO = 1577209972
    ERROR_DIFFERENT_USER = 1577209973
    ERROR_MOUNT_PATH = 1577209974
    ERR_DATABASE_STATUS = 1577210000
    ERROR_USER_NOT_EXIST_CLUSTER = 0x5E0250D7
    ERR_RESTORED = 1577210101
    # 不支持修改数据库名称
    ERROR_RENAME_DATABASE_NAME = 1577209901
    # 某个服务未正常开启，返回参数 服务名称
    ERROR_SERVICE_1577213479 = 1577213479
    # 数据库不存在，返回参数 数据库名称
    ERROR_DB_NOT_EXIST = 1577213477
    # 认证信息错误
    ERROR_AUTH = 1577209942
    # 参数错误
    ERROR_PARAM = 1677929218
    SYSTEM_ID_NOT_EXIST = 0
    DB_NODES_NOT_FULL_MATCH = 1677931026
    DB_ENV_ERROR = 2
    ACCESS_DB_ERROR = 3
    TENANT_MODEL_NOT_SUPPORT = 4
    DB_NOT_EXIST = 5
    # 不能修改数据库为新的数据库
    ERR_RENAME_DATABASE = 1577213482
    # 系统异常
    SYSTEM_ERROR = 1677929221
    # 不是所有数据库的服务都运行
    NOT_ALL_DB_SERVICE_RUNNING = 9
    # 增量转全量
    INC_TO_FULL = 0x5E02502D
    # 数据库不存在
    ERR_DB_NOT_EXIST = 1577210047
    # 部署类型错误
    ERR_DEPLOY_TYPE = 0x5E02508B
    # 版本不支持
    ERR_NOT_SUPPORT_VERSION = 1677935120
    # 数据库环境异常不支持备份恢复
    ERR_ENVIRONMENT = 1577213475
    # 账号密码错误
    LOGIN_FAILED = 1677929488
    # 数据库服务异常
    ERR_DB_SERVICES = 1577213479
    # 输入参数错误
    ERR_INPUT_STRING = 1677934101
    # 主机选择有误
    ERR_CHOSEN_HOSTS = 1577209936
    # 备份或者恢复失败
    ERR_BACKUP_RESTORE = 1677930292
    # region 不一致
    ERR_REGION = 1577210146
    # 资源接入异常 0x5E025120
    ERR_RESOURCE_ABILITY = 1577210144
    # 配置数据库备份流量控制、备机备份和数据压缩失败
    ERR_GAUSSDB_CONF = 1677873253


# 以下三个待确认
class LastCopyType:
    FULL_DIFF_COPIES = ["full", "diff"]
    FULL_COPIES = ["full"]
    LOG_COPIES = ["log"]
    ALL_COPIES = ["full", "diff", "log"]


class BackupTypeEnum(int, Enum):
    # 备份类型
    FULL_BACKUP = 1
    INCRE_BACKUP = 2
    DIFF_BACKUP = 3
    LOG_BACKUP = 4


class BusinessConfigType:
    # XBSA业务类型
    # 全备
    FULL_BACKUP_TYPE = 0
    # 增备
    INCREMENT_BACKUP_TYPE = 1
    # 全恢
    FULL_RESTORE_TYPE = 2
    # 差恢
    INCREMENT_RESTORE_TYPE = 3


class GaussCopyType:
    FULL = "full"
    DIFF = "diff"
    LOG = "log"
    S3ARCHIVE = "s3Archive"


# 应该只要到4了，待确认
class SubJobPriorityEnum(int, Enum):
    JOB_PRIORITY_1 = 1
    JOB_PRIORITY_2 = 2
    JOB_PRIORITY_3 = 3
    JOB_PRIORITY_4 = 4
    JOB_PRIORITY_5 = 5


class InstanceStatus:
    ACTIVE = "ACTIVE"
    INACTIVE = "INACTIVE"
    NORMAL = "normal"


class PermissionNode:
    # 权限码
    PERMISSION_755 = stat.S_IRWXU | stat.S_IXGRP | stat.S_IRGRP | stat.S_IROTH | stat.S_IXOTH
    PERMISSION_750 = stat.S_IRWXU | stat.S_IXGRP | stat.S_IRGRP
    PERMISSION_700 = stat.S_IRWXU
    PERMISSION_555 = stat.S_IRUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH
    PERMISSION_600 = stat.S_IRUSR | stat.S_IWUSR
    PERMISSION_640 = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP
    PERMISSION_644 = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
    PERMISSION_400 = stat.S_IRUSR


class UserInfo:
    # root用户
    USER_ROOT = "root"
    # rdadmin用户
    USER_RDADMIN = "rdadmin"


class TaskTypeEnum(int, Enum):
    # 备份类型
    BACKUP = 0
    RESTORE = 1


class RpcParamKey:
    APPLICATION = "application"
    TYPES = "types"
    FULL_COPY = "full"
    INCREMENT_COPY = "increment"
    COPY_ID = "copyId"
    JOB_ID = "jobId"
    INPUT_FILE_PREFFIX = "rpcInput"
    OUTPUT_FILE_PREFFIX = "rpcOutput"
    QUERY_PREVIOUS_CPOY = "QueryPreviousCopy"
    REPORT_COPY_INFO = 'ReportCopyAdditionalInfo'
    RPC_TOOL = f"{get_install_head_path()}/DataBackup/ProtectClient/Plugins/GeneralDBPlugin/bin/rpctool.sh"
    # 输入参数文件目录
    PARAM_FILE_PATH = f"{get_install_head_path()}/DataBackup/ProtectClient/Plugins/GeneralDBPlugin/tmp"
    # 输出结果文件目录
    RESULT_PATH = f"{get_install_head_path()}/DataBackup/ProtectClient/Plugins/GeneralDBPlugin/stmp"
    # backUpAgent没启动
    ERR_BACKUP_AGENT_NOT_START = "backUpAgent is not start"
    # 实例信息不一致
    INSTANCE_VERSION_IS_NOT_SAME = '1577326423'
    # 请求结果返回成功
    REST_SUCCESS = "SUCCESS"
    # 密码输入错误
    WRONG_UN_PASSWORD = "WRONG_UN_PSWD"
    # 请求结果返回成功
    MAX_TARGET_LENGTH = 128


class ErrorCodeType:
    error_code_type_dict = {
        # 备份时监控未开启
        'backup previous verify fail. cluster is not monitored': '1577326167',
        # 恢复时监控未开启
        'start backup restore fail. instance is not be monitored': '1577326167',
        # 备份路径未添加
        'backup previous verify fail. backup root path is not exist': '1577326168',
        # 单节点实例不支持日志备份
        'Manual log archiving failed,Kernel is not support': '1577326169',
        # 部署形态、分片数、版本号一致才能新位置恢复
        'fail to restore to another instance. backup version and instance version is not same': '1577326423',
        # 多节点实例时间差距超过10秒，日志归档检测失败
        'Manual log archiving failed,Log archiving is not enabled for the rootPath': '1577326424',
        # 未开启backupAgent备份失败
        'backUpAgent is not start': '1577326425',
        # 执行日志备份操作前或正在执行日志备份时，由于数据库实例发生节点重启或主备切换，操作失败。
        'The recovery time is invalidxlog has been archived': '1577212176',
        # 执行资源接入/备份/恢复操作时，由于帐户被锁定，导致操作失败。
        'Current user is processing, Please try again later': '1581404432',
        # 执行资源接入/备份/恢复操作时，由于帐户被锁定，导致操作失败。
        'ACCOUNT_LOCKED': '1581404432',
        # 执行备份/恢复操作时，由于数据库状态异常，操作失败。
        'The cluster status does not satisfy constraint for xbsa backup': '1578258688',
        # 执行备份/恢复操作时，由于数据库状态异常，操作失败。
        'start backup restore fail.instance status is abnormal': '1578258688',
        # 执行备份或恢复操作时，由于代理与数据库实例网络不通，导致操作失败。
        'No route to host': '1577326167'
    }


class EnvName:
    IAM_USERNAME = ""
    IAM_PASSWORD = ""
    IAM_BELONG = ""


class NormalErr(int, Enum):
    NO_ERR = 0
    FALSE = -1
    WAITING = -2


class ProgressInfo(str, Enum):
    START = "Start to do restore"
    FAILED = "Failed to do gbase task"
    SUCCEED = "Succeed to do gbase task"


class GaussDBPath:
    GaussDB_FILESYSTEM_MOUNT_PATH = "/mnt/databackup/"
    GaussDB_LINK_PATH = f"{get_install_head_path()}/DataBackup/"


class CMDResult(str, Enum):
    SUCCESS = "0"
    FAILED = "1"


class GaussDBBackupSubjobName:
    ROACH = "roach"
    EXEC = "exec"


class JobType(int, Enum):
    REGISTER = 1
    CHANGE = 2


class SubJobType(int, Enum):
    PRE_SUB_JOB = 0,
    GENERATE_SUB_JOB = 1,
    BUSINESS_SUB_JOB = 2,
    POST_SUB_JOB = 3


class SubJobPolicy(int, Enum):
    LOCAL_NODE = 1,
    EVERY_NODE_ONE_TIME = 2,
    RETRY_OTHER_NODE_WHEN_FAILED = 3,
    FIXED_NODE = 4


class GaussSubJobName:
    SUB_XBSA = "sub_xbsa"
    SUB_ROACH = "sub_roach"
    SUB_EXEC = "sub_exec"
    SUB_MERGE_DB = "sub_merge_db"
    SUB_QUERY_COPY = "queryCopy"


class GaussDBCode(Enum):
    """
    返回给框架的code
    """
    SUCCESS = 0
    FAILED = 200


class GaussBackupType:
    FULL = "completed"
    DIFF = "differential"
    LOG = "log"


class GaussBackupStatus:
    SUCCEED = 'Completed'
    RUNNING = "Running"


class GaussLogBackupStatus:
    SUCCEED = 'COMPLETED'
    RUNNING = "BUILDING"
    FAIL = "FAILED"


class GaussDBRdsErrorCode:
    REPEAT_CHANGE_BACKUP_MEDIA_TO_XBSA = "DBS.06015006"


class LogLevel(int, Enum):
    INFO = 1
    WARN = 2
    ERROR = 3
    SERIOUS = 4


class PermissionInfo(BaseModel):
    user: str = Field(default='root', description='user')
    group: str = Field(default='root', description='group')
    file_mode: str = Field(default='0700', description='mod', alias='fileMode')


class ActionResponse(BaseModel):
    code: int = Field(default=0, description="执行结果")
    body_err: int = Field(None, description="错误码", alias='bodyErr')
    message: str = Field(default='', description="错误信息")
    body_err_params: list = Field(None, description="错误码具体参数", alias="bodyErrParams")


class RequestStatusCode(int, Enum):
    SUCCESS = 201


class ExtendInfoKeys:
    BACKUP = "BackupSet"
    XBSA = "XbsaRoute"


class VERSION:
    TPOPS = "0"
    CONVERGENT = "1"


@dataclass
class JobInfo:
    """
    任务相关参数信息
    """
    copy_id: str
    job_id: str
    # 恢复或者备份
    type: str = None
    pid: str = None
    usr: str = None
    env_path: str = None
    sub_job_id: str = None
    sub_job_type: str = None
    cache_path: str = None
    meta_path: str = None
    meta_rep: dict = None
    cache_rep: dict = None
    data_reps: list = None
    metadata_destination: str = None
    backup_type: int = None
    progress: int = None
    task_status: int = None
    backup_result: int = None
    storage_id: str = None
    protect_env: dict = None
    backup_tool_type: int = None
    res_name: str = None
    nodes: list = None
    pro_obj_extend_info: dict = None
    pro_obj: dict = None
    storage_esn: set = None
    agents: list = None
    failed_agents: list = None
    cluster_agents: list = None
    host_agents: list = None
    open_source_delete: bool = False  # 此次备份是否开启源端重删
    # 日志信息
    log_detail: dict = None
    # 错误码
    error_code: str = None
    # 实例ID
    instance_id: str = None
    # 用户名
    user_name: str = None
    # 项目ID
    project_domain: str = None
    # 项目名
    project_name: str = None
    # 项目地址
    addr: str = None

    def log_format(self):
        """
        功能： 日志格式化返回
        """
        return f"pid: {self.pid}, job_id: {self.job_id}, sub_job_id: {self.sub_job_id}"

    def log_usr_env_path_format(self):
        return f"usr: {self.usr}, env_path: {self.env_path}"


REQUEST_SUCCESS_CODE = [201, 200]

WHITE_LIST = ''

QUERY_SIZE = 100

# 备份流控限速最小值和最大值
BACKUP_RATE_LIMIT_MIN = 0
BACKUP_RATE_LIMIT_MAX = 1024

# 备份流控限速默认值
BACKUP_RATE_LIMIT_NORMAL = 75

# 最大查询重试次数
MAX_QUERY_JOB_TIMES = 60

# 查询间隔时间
QUERY_JOB_INTERVAL = 30

# 超时5秒
TPOPS_TIMEOUT_FIVE_SECONDS = 5

# 超时60秒
TPOPS_TIMEOUT_SIXTY_SECONDS = 60


@dataclass
class RequestInfo:
    """
    任务相关参数信息
    """
    # 请求的URL地址
    request_url: str = None
    # 请求的正文内容，以字典形式存储
    request_body: dict = None
    # 请求的头部信息，以字典形式存储
    request_header: dict = None
    # 请求的方法，如GET、POST等
    request_method: str = None
    # 请求等待时间，默认5秒
    request_timeout: int = 5


class RequestMethodType:
    # 定义GET请求方法
    GET = 'get'
    # 定义POST请求方法
    POST = 'post'
    # 定义PUT请求方法
    PUT = 'put'
